import pygame as pg
from pygame import Surface
from pygame.sprite import Group, OrderedUpdates, Sprite, groupcollide, collide_circle
from pygame.locals import *
from math import sin, pi
from numpy import clip
from time import sleep

from sprites import Text, Ball, Paddle
import actions, map_creater
pg.init()
f = pg.font.Font('Ubuntu-B.ttf', 50)

scene = None

def gcollide(g1,g2):
    return groupcollide(g1, g2, False, False)

class Scene(OrderedUpdates):
    def __init__(self):
        OrderedUpdates.__init__(self)  
        self.coords = pg.Rect(0,0,0,0)
        self.gui = None
        global scene
        scene = self

    def event (self, e):
        if self.gui:
            self.gui.event(e)

class Intro(Scene):
    def __init__(self):
        Scene.__init__(self)
        txt = Text(f, "Pythanoid 0.1", (255,200,200), (0,0))
        self.add(txt)
        txt2 = Text(f, "Click to start", (0,0,0), (100,300))
        self.add(txt2)

        def upd():
            delay = 20
            phase = clip((self.time-delay)/10.0,0,  pi/2.0)
            off = 360
            txt.rect.topleft = (int(-off+sin(phase)*off)+50,
                                50)
            delay2 = 30
            color = clip((self.time-delay2)*3,0,255)
            txt2.image = f.render("Click to start (Q quits)", 1, [color]*3)         
            self.time += 1
        txt.update = upd
        self.time = 1

    def event(self, e):
        if e.type == KEYDOWN:
            actions.new_game()
        elif e.type == MOUSEBUTTONDOWN:
            actions.new_game()

class Level(Scene):
    def __init__(self, lvln):
        Scene.__init__(self)
        self.lvln = lvln
        self.bonus_chance, blocks = map_creater.create(lvln)
        self.blocks = Group(blocks)
        self.balls = Group(Ball())
        self.pads = Group(Paddle())
        self.bonuses = Group()
        map(self.add, [self.blocks, self.balls, self.pads])
        self.size = pg.display.get_surface().get_size()
        self.fade_in_setup()

    def play(self):
        Scene.update(self)
        for b in self.balls:
            b.move()
            bc = b.coords
            if bc[0] < 0+b.radius:
                b.speed[0] = abs(b.speed[0])
            if bc[0] > self.size[0]:
                b.speed[0] = -abs(b.speed[0])
            if bc[1] < 0+b.radius:
                b.speed[1] = abs(b.speed[1])
            if bc[1] > self.size[1]:
                b.kill()
        for ball, bricks in gcollide(self.balls, self.blocks).items():
            if len(bricks)>1:
                ball.speed = -ball.speed
            else:
                ball.collide(bricks[0])
            for b in bricks:
                b.hit()
        for ball, pads in gcollide(self.balls, self.pads).items():
            ball.paddle_bounce(pads[0])
        if not self.balls:
            self.game_over()
            return
        if not self.blocks:
            self.win()
            return
        for bonus, pads in gcollide(self.bonuses, self.pads).items():
            bonus.pickup(pads[0])

    def game_over(self):
        self.timer = 1
        self.fader = Sprite()
        self.fader.image = Surface(self.size,SRCALPHA)
        self.fader.rect = self.fader.image.get_rect()
        self.add(self.fader)
        self.update = self.fade_away

    def fade_away(self):
        if self.timer >= 200:
            actions.game_over()
        self.fader.image.fill(pg.Color(0,0,0,self.timer))
        self.timer += 10

    def fade_in_setup(self):
        self.timer = 1
        self.fader = Sprite()
        self.fader.image = Surface(self.size,SRCALPHA)
        self.fader.rect = self.fader.image.get_rect()
        self.add(self.fader)
        self.update = self.fade_in
        self.txt = Text(f,
                        "Level "+str(self.lvln)+". Click to continue",
                        (230,230,230,50),
                        (200,400))
        self.add(self.txt)
        old_event = self.event
        def event(e):
            if e.type == MOUSEBUTTONDOWN:
                self.fader.kill()
                self.txt.kill()
                self.update = self.play
                self.event = old_event
        self.event = event
        
    def fade_in(self):
        delay = 30
        if self.timer-delay >= 60:
            return
        
        alpha = 255-clip(self.timer-delay,0,60)*4
        self.fader.image.fill(pg.Color(0,0,0,int(alpha)))
        self.timer += 2

    def win(self):
        self.update = lambda:None
        actions.next_lvl()

def GameOver():
    s = Scene()
    txt = Text(f, "You lost! Click to try again", [255,200,200], (100,100))
    s.add(txt)
    def event(e):
        if e.type in [KEYDOWN, MOUSEBUTTONDOWN]:
            actions.new_game()
    s.event = event
    return s

def Win():
    s = Scene()
    txt = Text(f, "You win!", [255,200,200], (100,100))
    s.add(txt)
    def event(e):
        if e.type in [KEYDOWN, MOUSEBUTTONDOWN]:
            actions.record_table()
    s.event = event
    return s


def trans(scene1, scene2):
    #TODO Transition
    return scene2
